package com.chuhe.starry.service.impl;

import com.chuhe.common.domain.dto.MessageSendDto;
import com.chuhe.common.domain.dto.TokenUserInfoDto;
import com.chuhe.common.domain.entity.*;
import com.chuhe.common.domain.enums.*;
import com.chuhe.common.domain.vo.req.ApplyAddReq;
import com.chuhe.common.domain.vo.resp.SysSettingResp;
import com.chuhe.common.domain.vo.resp.UserConcactResp;
import com.chuhe.common.domain.vo.resp.loadContactInfoResp;
import com.chuhe.common.domain.vo.resp.loadContactResp;
import com.chuhe.common.exception.BusinessException;
import com.chuhe.common.exception.CommonErrorEnum;
import com.chuhe.common.utils.AssertUtil;
import com.chuhe.common.utils.RedisComponet;
import com.chuhe.common.utils.StringTools;
import com.chuhe.starry.dao.*;
import com.chuhe.starry.mapper.ChatMessageMapper;
import com.chuhe.starry.mapper.ChatSessionMapper;
import com.chuhe.starry.mapper.ChatSessionUserMapper;
import com.chuhe.starry.mapper.UserContactMapper;
import com.chuhe.starry.service.UserContactService;
import com.chuhe.starry.service.adapter.UserContactAdapter;
import com.chuhe.starry.websocket.ChannelContextUtils;
import com.chuhe.starry.websocket.MessageHandler;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @Author: 楚河
 * @Date: 2025年05月11日13:51
 */
@Service
public class UserContactServiceImpl implements UserContactService {
    @Autowired
    private UserContactDao userContactDao;
    @Autowired
    private GroupInfoDao groupInfoDao;
    @Autowired
    private UserInfoDao userInfoDao;
    @Autowired
    private RedisComponet redisComponet;
    @Autowired
    private UserContactMapper userContactMapper;
    @Autowired
    private ChannelContextUtils channelContextUtils;
    @Autowired
    private ChatSessionDao chatSessionDao;
    @Autowired
    private ChatMessageDao chatMessageDao;
    @Autowired
    private ChatSessionUserDao chatSessionUserDao;
    @Autowired
    private MessageHandler messageHandler;
    @Autowired
    private ChatMessageMapper chatMessageMapper;
    @Autowired
    private ChatSessionUserMapper chatSessionUserMapper;
    @Autowired
    private ChatSessionMapper chatSessionMapper;


    /**
     * 搜索联系人
     * @Author: 楚河
     * @Date: 2025-05-15 22:33
     */
    @Override
    public UserConcactResp searchContact(String userId, String contactId) {
        //区分contactId是用户Id还是组Id
        UserContactTypeEnum prefix = UserContactTypeEnum.getByPrefix(contactId);
        if(Objects.isNull(prefix)){
            return null;
        }
        //查询用户或组
        UserConcactResp userConcactResp = new UserConcactResp();
        switch (prefix) {
            case USER:
                UserInfo userInfo = userInfoDao.selectByUserId(contactId);
                if(Objects.isNull(userInfo)){
                    return null;
                }
                BeanUtils.copyProperties(userInfo, userConcactResp);
                break;
            case GROUP:
                GroupInfo groupInfo = groupInfoDao.selectGroupId(contactId);
                if(Objects.isNull(groupInfo)){
                    return null;
                }
                userConcactResp.setNickName(groupInfo.getGroupName());
                break;
        }
        userConcactResp.setContactType(prefix.toString());
        userConcactResp.setContactId(contactId);
        //如果是自己
        if(userId.equals(contactId)){
            userConcactResp.setStatus(UserContactStatusEnum.FRIEND.getStatus());
            return userConcactResp;
        }
        //查询是否是好友
        UserContact userContact = userContactDao.selectByUserIdAndContactId(userId,contactId);
        userConcactResp.setStatus(userContact == null ? null : userContact.getStatus());
        return userConcactResp;
    }

    /**
     * 添加联系人
     * @Author: 楚河
     * @Date: 2025-05-17 10:48
     */
    @Override
    @Transactional
    public void addUserContact(String userId,
                               String contactId,
                               String applyInfo,
                               String receiveUserId,
                               Integer contactType) {
        //若是群组 查看所在群组人数是否已满足上限
        if(UserContactTypeEnum.GROUP.getType().equals(contactType)){
            //获取该群组人数
            UserContact userContact = UserContactAdapter.buildSelectOnGroupCount(contactId,UserContactStatusEnum.FRIEND.getStatus());
            Integer count = userContactDao.getOnGroupCount(userContact);
            //获取群组配置
            SysSettingResp sysSetting = redisComponet.getSysSetting();
            AssertUtil.isTrue(count >= sysSetting.getMaxGroupMemberCount(),"群成员已达上限，无法加入");
        }
        //如果存在库信息 互相更新状态操作
        UserContact userContact = userContactDao.selectByUserIdAndContactId(userId, contactId);
        if(!Objects.isNull(userContact)){
            userContactDao.updateContactStatus(userId,contactId,UserContactStatusEnum.FRIEND.getStatus());
            userContactDao.updateContactStatus(contactId,userId,UserContactStatusEnum.FRIEND.getStatus());
        }else {
            //若是好友 同意 双方加为好友 双方好友联系人信息入库
            //申请人添加对方
            Date date = new Date();
            UserContact AddReceiveUserContact = UserContactAdapter.buildAddReceiveUserContact(userId,contactId,contactType,date);
            userContactDao.save(AddReceiveUserContact);
            //对方添加申请人  群组不需要
            if(UserContactTypeEnum.USER.getType().equals(contactType)){
                UserContact receiveAddUserContact = UserContactAdapter.buildReceiveAddUserContact(receiveUserId,userId,contactType,date);
                userContactDao.save(receiveAddUserContact);
            }
        }

        //如果是好友申请,接收人也添加申请人为联系人 缓存
        if (UserContactTypeEnum.USER.getType().equals(contactType)) {
            redisComponet.addUserContact(receiveUserId, userId);
        }
        //审核通过，将申请人的联系人添加上 我 或 群组 缓存
        redisComponet.addUserContact(userId, contactId);

        //加完好友ws发消息
        String sessionId = null;
        if(UserContactTypeEnum.USER.getType().equals(contactType)){
            sessionId = StringTools.getChatSessionId4User(new String[]{userId,contactId});
        }else {
            sessionId = StringTools.getChatSessionId4Group(contactId);
        }
        //会话参与人
        List<ChatSessionUser> chatSessionUserList = new ArrayList<>();
        if(UserContactTypeEnum.USER.getType().equals(contactType)){
            //创建会话的最后一条消息显示
            ChatSession chatSession = new ChatSession();
            chatSession.setSessionId(sessionId);
            chatSession.setLastReceiveTime(new Date().getTime());
            chatSession.setLastMessage(applyInfo);
            chatSessionMapper.saveOrUpdate(chatSession);
            //申请人session
            ChatSessionUser chatSessionUser = new ChatSessionUser();
            chatSessionUser.setUserId(userId);
            chatSessionUser.setContactId(contactId);
            chatSessionUser.setSessionId(sessionId);
            chatSessionUser.setLastReceiveTime(new Date().getTime());
            chatSessionUser.setLastMessage(applyInfo);
            UserInfo userInfo = userInfoDao.selectByUserId(contactId);
            chatSessionUser.setContactName(userInfo.getNickName());
            chatSessionUserList.add(chatSessionUser);

            //接收人session
            ChatSessionUser chatSessionContact = new ChatSessionUser();
            chatSessionContact.setUserId(contactId);
            chatSessionContact.setContactId(userId);
            chatSessionContact.setSessionId(sessionId);
            chatSessionContact.setLastReceiveTime(new Date().getTime());
            chatSessionContact.setLastMessage(applyInfo);
            UserInfo receiveUserInfo = userInfoDao.selectByUserId(userId);
            chatSessionUser.setContactName(receiveUserInfo.getNickName());
            chatSessionUserList.add(chatSessionContact);
            chatSessionUserMapper.saveOrUpdate(chatSessionUserList);

            //记录消息表
            ChatMessage chatMessage = new ChatMessage();
            chatMessage.setSessionId(sessionId);
            chatMessage.setMessageType(MessageTypeEnum.ADD_FRIEND.getType());
            chatMessage.setMessageContent(applyInfo);
            chatMessage.setSendUserId(userId);
            chatMessage.setSendUserNickName(receiveUserInfo.getNickName());
            chatMessage.setSendTime(new Date().getTime());
            chatMessage.setContactId(contactId);
            chatMessage.setContactType(UserContactTypeEnum.USER.getType());
            chatMessage.setStatus(MessageStatusEnum.SENDED.getStatus());
            chatMessageDao.save(chatMessage);

            //组装发送的消息体
            MessageSendDto messageSendDto = new MessageSendDto();
            BeanUtils.copyProperties(chatMessage,messageSendDto);
            //发送给接受好友申请的人
            messageHandler.sendMessage(messageSendDto);
            //发送给申请人，发送人就是接收人，联系人就是申请人
            messageSendDto.setMessageType(MessageTypeEnum.ADD_FRIEND_SELF.getType());
            messageSendDto.setContactId(userId);
            messageSendDto.setExtendData(userInfo);
            messageHandler.sendMessage(messageSendDto);
        }else {
            //群组消息
            List<ChatSessionUser> chatSessionGroupUserList = new ArrayList<>();
            ChatSessionUser chatSessionUser = new ChatSessionUser();
            chatSessionUser.setUserId(userId);
            chatSessionUser.setContactId(contactId);
            GroupInfo groupInfo = groupInfoDao.selectByGroupId(contactId);
            chatSessionUser.setContactName(groupInfo.getGroupName());
            chatSessionUser.setSessionId(sessionId);
            chatSessionGroupUserList.add(chatSessionUser);
            chatSessionUserMapper.saveOrUpdate(chatSessionGroupUserList);

            //将群组加入到用户的联系人列表
            redisComponet.addUserContact(userId,groupInfo.getGroupId());
            channelContextUtils.addUser2Group(userId,groupInfo.getGroupId());

            UserInfo applyUserInfo = userInfoDao.selectByUserId(userId);
            String sendMessage = String.format(MessageTypeEnum.ADD_GROUP.getInitMessage(),applyUserInfo.getNickName());

            //添加session信息
            Date curDate = new Date();
            ChatSession chatSession = new ChatSession();
            chatSession.setSessionId(sessionId);
            chatSession.setLastReceiveTime(curDate.getTime());
            chatSession.setLastMessage(sendMessage);
            chatSessionMapper.saveOrUpdate(chatSession);

            //组装聊天消息
            ChatMessage chatMessage = new ChatMessage();
            chatMessage.setSessionId(sessionId);
            chatMessage.setMessageType(MessageTypeEnum.ADD_GROUP.getType());
            chatMessage.setMessageContent(sendMessage);
            chatMessage.setSendUserId(null);
            chatMessage.setSendUserNickName(null);
            chatMessage.setSendTime(curDate.getTime());
            chatMessage.setContactId(contactId);
            chatMessage.setContactType(UserContactTypeEnum.GROUP.getType());
            chatMessage.setStatus(MessageStatusEnum.SENDED.getStatus());
            chatMessageDao.save(chatMessage);

            //发送群消息
            MessageSendDto messageSendDto = new MessageSendDto();
            BeanUtils.copyProperties(chatMessage, messageSendDto);
            messageSendDto.setContactId(groupInfo.getGroupId());
            //获取群聊的人员数量
            Integer count = userContactDao.selectGroupCount(groupInfo.getGroupId());
            messageSendDto.setMemberCount(count);
            messageSendDto.setContactName(groupInfo.getGroupName());
            messageHandler.sendMessage(messageSendDto);
        }
    }

    /**
     * 加载联系人列表
     * @Author: 楚河
     * @Date: 2025-05-17 13:39
     */
    @Override
    public List<loadContactResp> findContactList(String userId, String contactType) {
        //校验请求类型
        UserContactTypeEnum contactTypeEnum = UserContactTypeEnum.getByName(contactType);
        AssertUtil.isEmpty(contactTypeEnum,CommonErrorEnum.CODE_600);

        //查询好友或群组
        UserContact userContact = UserContactAdapter.buildFindUserOrGroup(userId,contactTypeEnum.getType());
        List<loadContactResp> list = userContactMapper.findUserOrGroup(userContact);
        return list;
    }

    /**
     * 加载联系人详情 *
     * @Author: 楚河
     * @Date: 2025-05-17 16:27
     */
    @Override
    public loadContactInfoResp loadContactInfo(String userId, String contactId) {
        //查询用户
        UserInfo userInfo = userInfoDao.selectByUserId(contactId);
        loadContactInfoResp loadContactInfoResp = new loadContactInfoResp();
        BeanUtils.copyProperties(userInfo, loadContactInfoResp);
        loadContactInfoResp.setContactStatus(UserContactStatusEnum.NOT_FRIEND.getStatus());
        //检查是否是好友
        UserContact userContact = userContactDao.selectByUserIdAndContactId(userId,contactId);
        if(Objects.nonNull(userContact)){
            loadContactInfoResp.setContactStatus(userContact.getStatus());
        }
        return loadContactInfoResp;
    }

    /**
     * 加载联系人详情
     * @Author: 楚河
     * @Date: 2025-05-17 16:37
     */
    @Override
    public loadContactInfoResp getContactUserInfo(String userId, String contactId) {
        //检查是否是好友
        UserContact userContact = userContactDao.selectByUserIdAndContactId(userId,contactId);
        if(Objects.isNull(userContact)
            || userContact.getStatus().equals(UserContactStatusEnum.DEL)
            || userContact.getStatus().equals(UserContactStatusEnum.BLACKLIST)
            || userContact.getStatus().equals(UserContactStatusEnum.NOT_FRIEND)){
            throw new BusinessException(CommonErrorEnum.CODE_600);
        }
        //查询用户
        UserInfo userInfo = userInfoDao.selectByUserId(contactId);
        loadContactInfoResp loadContactInfoResp = new loadContactInfoResp();
        BeanUtils.copyProperties(userInfo, loadContactInfoResp);
        loadContactInfoResp.setContactStatus(userContact.getStatus());
        return loadContactInfoResp;
    }

    /**
     * 删除联系人
     * @Author: 楚河
     * @Date: 2025-05-17 16:48
     */
    @Override
    public Objects delContact(String userId, String contactId, UserContactStatusEnum statusEnum) {
        //更新双方库信息
        UserContact userContact = new UserContact();
        userContact.setStatus(statusEnum.getStatus());
        userContactDao.updateByUserIdAndContactId(userContact,userId,contactId);
        //好友中也移除自己
        UserContact friendContact = new UserContact();
        if(UserContactStatusEnum.DEL == statusEnum){
            friendContact.setStatus(UserContactStatusEnum.DEL_BE.getStatus());
        }else if(UserContactStatusEnum.BLACKLIST == statusEnum){
            friendContact.setStatus(UserContactStatusEnum.BLACKLIST_BE.getStatus());
        }
        userContactDao.updateByUserIdAndContactId(friendContact,contactId,userId);
        //将我从对方Redis好友缓存中删除
        redisComponet.removeuserContact(contactId,userId);
        //将对方从我Redis好友缓存中删除
        redisComponet.removeuserContact(userId,contactId);
        return null;
    }

}
